import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;

import agentFramework.action.Action;
import agentFramework.core.env.Environment;
import agentFramework.strategy.QLStrategy;
import agentFramework.tools.InfluenceGroup;
import agentFramework.tools.LeaderDetector;
import agentFramework.utils.Pair;


public class ScenarioDrawingArea extends AbstractDrawingArea implements MouseMotionListener
{
	private final int 	POINT_RADIUS = 5;
	
	private Pair<Integer, Integer>[] 	point;
	private int							nPoints;
	
	private boolean						bDrawText;
	private String						text;
	private int							textX;
	private int							textY;
	
	
	public ScenarioDrawingArea(Window gui)
	{
		super(gui);
		
		point 	= null;
		nPoints = 0;
		text = "";
		bDrawText = false;
		this.addMouseMotionListener(this);
	}
	
	
	public boolean isEnvironmentLoaded()
	{
		return ((gui.env != null) && (gui.core != null));
	}
	
	
	private void computeCoordinates()
	{
		System.out.println("computing coordinates");
		
		int					width = this.getWidth();
		int					height = this.getHeight();
		Environment			env =   gui.env;
		ArrayList< Pair<Integer, Pair<Integer, Integer> > > pointList;
		
		pointList = GraphSpanner.span(env.getAgentCount(), 
				  	env.getNeighborMatrix(),
				  	0,
				  	0,
				  	width,
				  	height,
				  	2 * Math.PI / env.getAgentCount(),
				  	Math.min(width, height) / env.getAgentCount(),
				  	3
				  	);
		
		this.nPoints = pointList.size();
		point = new Pair[nPoints];
		
		for (Pair< Integer, Pair<Integer, Integer> > p : pointList)
		{
			point[p.first] = p.second;
		}
		
		System.out.println("coordinates computed");
	}
	
	
	private boolean isLeader(int id, ArrayList<InfluenceGroup> groupList)
	{
		for (InfluenceGroup g : groupList)
		{
			if ((g.root == id) && (g.hasLeader)) return true;
		}
			
		return false;
	}
	
	
	@Override
	public void drawScenario(Graphics g) 
	{
		if (!isEnvironmentLoaded()) return;

		
		int 				width = this.getWidth();
		int 				height = this.getHeight();
		Environment			env =  gui.env;
		boolean[][]			edge = env.getNeighborMatrix();
		LeaderDetector		ld = null;
		
		if (point == null) computeCoordinates();
		
		if (env.getCore() instanceof IrishCore)
		{
			ld = ((IrishCore)env.getCore()).leaderDetector;
		}
		else
		{
			ld = ((DilemmaCore)env.getCore()).leaderDetector;
		}
		
		ld.findLeaders();
		
		g.setColor(Color.WHITE);
		g.clearRect(0, 0, width, height);
		
		// draw the points
		g.setColor(Color.BLACK);
		for (int i = 0; i < nPoints; i++)
		{
			int 	x = point[i].first;
			int 	y = point[i].second;
			Action	action = env.getAgentById(i).currentAction;
			Color 	fillColor = null; 
					
			if (action != null)
			{
				fillColor = (env.getAgentById(i).currentAction.getType() == 0) ? Color.RED : Color.GREEN;
			}
			
			if (isLeader(i, ld.getInfluenceGroups()))
			{
				g.drawRect(x - POINT_RADIUS, y - POINT_RADIUS, 2*POINT_RADIUS, 2*POINT_RADIUS);
				
				if (fillColor != null)
				{
					g.setColor(fillColor);
					g.fillRect(x - POINT_RADIUS, y - POINT_RADIUS, 2*POINT_RADIUS, 2*POINT_RADIUS);
				}
			}
			else
			{
				g.drawOval(x - POINT_RADIUS, y - POINT_RADIUS, 2*POINT_RADIUS, 2*POINT_RADIUS);
				
				if (fillColor != null)
				{
					g.setColor(fillColor);
					g.fillOval(x - POINT_RADIUS, y - POINT_RADIUS, 2*POINT_RADIUS, 2*POINT_RADIUS);
				}
			}
		}
		
		// draw the edges
		g.setColor(Color.BLUE);
		for (int i = 0; i < nPoints - 1; i++)
			for (int j = i + 1; j < nPoints; j++)
			{
				if (edge[i][j])
				{
					g.drawLine(point[i].first, point[i].second, point[j].first, point[j].second);
				}
			}
		
		if (bDrawText)
		{
			g.setColor(Color.BLACK);
			g.drawString(text, textX, textY);
		}
		
	}


	@Override
	public void mouseDragged(MouseEvent e) {
		// DO NOTHING
	}


	@Override
	public void mouseMoved(MouseEvent e) 
	{
		bDrawText = false;
		
		if ( (!isEnvironmentLoaded()) || (point == null) || (nPoints == 0) ) return;
		
		int 		mx = e.getX();
		int 		my = e.getY();
		
		for (int i = 0; i < nPoints; i++)
		{
			int px = point[i].first;
			int py = point[i].second;
			
			if ( (mx >= px - POINT_RADIUS) && (mx <= px + POINT_RADIUS) &&
				 (my >= py - POINT_RADIUS) && (my <= py + POINT_RADIUS) )
			{
				String agentType = "Bully";
				
				if (gui.env.getAgentById(i).agentStrategy instanceof QLStrategy)
				{
					agentType = "QLStrategy";
				}
				else if (gui.env.getAgentById(i).agentStrategy instanceof QLStrategy)
				{
					agentType = "EpsQLStrategy";
				}
				
				text  = agentType;
				textX = mx;
				textY = my;
				bDrawText = true;
				
				this.repaint();
				return;
			}
		}
		
		/* outside all points, do not redraw */
		bDrawText = false;
		this.repaint();
	}

}
